(function($) {
	
	var richtextarea = {
		
		options: {
			content_css_url: ''
		}
		
		, events: {
			pressEnter: 'pressEnter'
		}
		
		, _iframe: null
		
		, _create: function() {
			var self = this;
			
			self._enableDesignMode();
		}
		
        , _enableDesignMode: function () {
        	var self = this;
        	var textarea = self.element;
            var content = textarea.val();
            var iframe = self._iframe;

            // Mozilla needs this to display caret
            if($.trim(content)=='' && $.browser.mozilla) {
                content = '<br />';
            }

            // already created? show/hide
            if(iframe) {
                console.log("already created");
                textarea.hide();
                $(iframe).contents().find("body").html(content);
                $(iframe).show();
                
                return true;
            }

            // for compatibility reasons, need to be created this way
            iframe = document.createElement("iframe");
            iframe.frameBorder=0;
            iframe.frameMargin=0;
            iframe.framePadding=0;
            iframe.height= '100%';
            iframe.width = '100%';
            if(textarea.attr('class'))
                iframe.className = textarea.attr('class');
            if(textarea.attr('id'))
                iframe.id = textarea.attr('id');
            if(textarea.attr('name'))
                iframe.title = textarea.attr('name');

            textarea.after(iframe);
            
            self._iframe = iframe;

            var css = "";
            if(self.options.content_css_url) {
                css = "<link type='text/css' rel='stylesheet' href='" + self.options.content_css_url + "' />";
            }

            var doc = "<html><head>"+css+"</head><body class='frameBody'>"+content+"</body></html>";
            self._tryEnableDesignMode(doc, function() {
                // hide textarea
                textarea.hide();
            });

        }

        , _tryEnableDesignMode: function(doc, callback) {
        	var self = this;
            var iframe = self._iframe;        	
        	
            if(!iframe) { return false; }

            try {
            	var document = iframe.contentWindow.document;
            	document.open();
            	document.write(doc);
            	document.close();
                
            	$(document).keyup(function(e) {
                	if (e.keyCode == 13) {
                		self._trigger(self.events.pressEnter, new $.Event(self.events.pressEnter));
                	} 
            		return false;
            	});
                
            } catch(error) {
                //console.log(error);
            }
            if (document.contentEditable) {
                iframe.contentWindow.document.designMode = "On";
                callback();
                return true;
            }
            else if (document.designMode != null) {
                try {
                    iframe.contentWindow.document.designMode = "on";
                    callback();
                    return true;
                } catch (error) {
                    //console.log(error);
                }
            }
            setTimeout(function(){$.proxy(self._tryEnableDesignMode(doc, callback), self);}, 500);
            return false;
        }

        , _disableDesignMode: function(submit) {
        	var self = this;
            var iframe = self._iframe;   
            var textarea = self.element;
            var content = $(iframe).contents().find("body").html();

            if($(iframe).is(":visible")) {
                textarea.val(content);
            }

            if(submit !== true) {
                textarea.show();
                $(iframe).hide();
            }
        }
        
        , _formatText: function(command, option) {
        	var self = this;
            var iframe = self._iframe;   
            
            iframe.contentWindow.focus();
            try{
                iframe.contentWindow.document.execCommand(command, false, option);
            }catch(e){
                //console.log(e)
            }
            iframe.contentWindow.focus();
         	window.focus();   
        }
        
        , focus: function() {
        	var self = this;
            var iframe = self._iframe;
            
            iframe.contentWindow.focus();
        }

        , setSelectedType: function(node, select) {
            while(node.parentNode) {
                var nName = node.nodeName.toLowerCase();
                for(var i=0;i<select.options.length;i++) {
                    if(nName==select.options[i].value){
                        select.selectedIndex=i;
                        return true;
                    }
                }
                node = node.parentNode;
            }
            select.selectedIndex=0;
            return true;
        }

        , getSelectionElement: function() {
        	var self = this;
            var iframe = self._iframe; 
            
            if (iframe.contentWindow.document.selection) {
                // IE selections
                selection = iframe.contentWindow.document.selection;
                range = selection.createRange();
                try {
                    node = range.parentElement();
                }
                catch (e) {
                    return false;
                }
            } else {
                // Mozilla selections
                try {
                    selection = iframe.contentWindow.getSelection();
                    range = selection.getRangeAt(0);
                }
                catch(e){
                    return false;
                }
                node = range.commonAncestorContainer;
            }
            return node;
        }
        
        /**
         * @param img: image url or img dom or img jquery obj 
         */
        , insertImage: function(img) {
        	var self = this;
        	if (typeof(img) == 'string') {
        		self._formatText('InsertImage', img);
        	} else if (typeof(img) == 'object' && $(img).length > 0 && $(img).get(0).tagName.toLowerCase() == 'img') {
        		self._formatText('InsertImage', $(img).attr('src'));
        	} else {
        		alert('must url string or img dom');
        	}
        }
        
        , getContent: function() {
        	var self = this;
            var iframe = self._iframe; 
        	return iframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
        } 
        
        , setContent: function(val)  {
         	var self = this;
            var iframe = self._iframe; 
        	iframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML = $.browser.mozilla ? '<br/>' : '' + val;       	
        }    		
		
		, destroy: function () {
			$.Widget.prototype.destroy.call(this);
		}
		
	};
	
	$.widget('daniel.richtextarea', richtextarea);
	
})(jQuery);
